<template>
  <div class="w-full">
    <template v-if="!readonly">
      <Popup
        ref="popupRef"
        @ok="handleOk"
        :multiple="multiple"
        :title="placeholder"
        :list-options="listOptions"
        :display-field="displayField"
        :value-field="valueField"
        v-if="!disabled"
      />
      <el-select
        :placeholder="placeholder"
        v-model="inputValue"
        :multiple="multiple"
        :size="size"
        :disabled="disabled"
        @focus="popupClick"
        :clearable="!multiple"
        @remove-tag="removeTag"
        popper-class="y-popup--popper"
        class="w-full"
      >
        <el-option
          v-for="item in selectedCollections"
          :key="item[valueField]"
          :label="item[displayField]"
          :value="item[valueField]"
        ></el-option>
      </el-select>
    </template>

    <div v-else>
      {{ itemName }}
    </div>
  </div>
</template>

<script>
import { cloneDeep } from '@/utils'
import Popup from './components/popup.vue'

export default {
  props: {
    data: Object,
    /**
     * 大小
     * @values small, medium, large
     */
    size: {
      type: String
    },
    // 占位符
    placeholder: {
      type: String,
      default: '请选择'
    },
    // 是否多选
    multiple: {
      type: Boolean,
      default: false
    },
    // 表格配置
    listOptions: Object,
    // 绑定多组数据
    bounds: {
      type: Object,
      default: () => ({})
    },
    displayField: {
      type: String,
      required: true
    },
    // 值字段（关键字段）
    valueField: {
      type: String,
      required: true
    },
    // 是否禁用
    disabled: Boolean,
    // 只读
    readonly: Boolean
  },
  components: {
    Popup
  },
  data() {
    return {}
  },
  computed: {
    // 只读显示文字
    itemName() {
      return this.selectedCollections
        .map((item) => item[this.displayField])
        .join('、')
    },
    // input 显示内容
    inputValue: {
      get() {
        if (this.multiple) {
          return this.selectedCollections.map((item) => item[this.valueField])
        } else {
          return this.selectedCollections
            .map((item) => item[this.valueField])
            .join(',')
        }
      },
      set(e) {
        if (!e) {
          // 清空选中
          this.selectedCollections = []
        }
      }
    },
    formData: {
      get() {
        return this.data
      },
      set(e) {
        this.$emit('update:data', e)
      }
    },

    /**
     * 集合列表
     */
    selectedCollections: {
      get() {
        /**
         * 将value对象根据bounds配置映射为用户对象集合
         * 映射逻辑：遍历bounds的每个属性，拆解value对应属性值为数组元素
         * 按数组索引组合成完整用户对象
         */
        const bounds = this.bounds || {}
        return Object.keys(bounds)
          .reduce((acc, key) => {
            const field = bounds[key]
            const values = String(this.data?.[key] || '')
              .split(',')
              .map((v) => v.trim())

            values.forEach((val, index) => {
              acc[index] = acc[index] || {}
              acc[index][field] = val
            })
            return acc
          }, [])
          .filter((item) => Object.values(item).some((v) => v))
      },
      set(newVal) {
        /**
         * 将用户对象集合根据bounds配置逆向映射到value对象
         * 映射逻辑：遍历每个用户对象，按bounds配置收集属性值
         * 最终emit包含所有映射属性的value对象
         */
        const bounds = this.bounds || {}
        const mappedValue = Object.entries(bounds).reduce(
          (acc, [key, field]) => {
            acc[key] = newVal.map((item) => item?.[field] || '').join(',')
            return acc
          },
          {}
        )
        Object.entries(mappedValue).forEach(([key, value]) => {
          this.$set(this.formData, key, value)
        })
      }
    }
  },
  methods: {
    /**
     * 处理弹出层点击事件
     *
     * 函数通过 Vue ref 获取弹出层组件实例，调用其 open 方法打开弹窗
     * 调用时将当前选中的集合数据作为参数传递给弹出层组件
     *
     * @param {void}
     * @returns {void}
     */
    popupClick() {
      this.$refs.popupRef.open(this.selectedCollections)
    },
    /**
     * 处理确认操作，更新选中的集合数据
     * @param {any} e - 接收的确认事件参数/数据，通常包含用户选择的集合信息
     */
    handleOk(e) {
      this.selectedCollections = e
    },
    /**
     * 从选中的集合中移除指定用户ID对应的标签
     *
     * @param {string|number} valueField - 需要移除标签的用户唯一标识符
     * @returns {void} 无返回值，直接修改实例的selectedCollections数组
     */
    removeTag(valueField) {
      if (!Array.isArray(this.selectedCollections)) return

      const selected = cloneDeep(this.selectedCollections)

      const index = selected.findIndex(
        (item) => item[this.valueField] === valueField
      )
      if (index > -1) {
        selected.splice(index, 1)
        this.selectedCollections = selected
      }
    }
  }
}
</script>

<style lang="scss">
.y-popup--popper {
  display: none !important;
}
</style>
